<html>
  <head>
    <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>SpringMVC_2 响应数据、文件上传、异常处理、拦截器 | 清汤牛肉锅</title>
<meta name="description" content="温故而知新
" />
<link rel="shortcut icon" href="https://ArtZoick.github.io//favicon.ico?v=1572228390311">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.10.0/katex.min.css">
<link rel="stylesheet" href="https://ArtZoick.github.io//styles/main.css">

<script src="https://cdn.bootcss.com/highlight.js/9.12.0/highlight.min.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Droid+Serif:400,700">


<script async src="https://www.googletagmanager.com/gtag/js?id=UA-143265163-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-143265163-1');
</script>


  </head>
  <body>
    <div class="main">
      <div class="main-content">
        <div class="site-header">
  <a href="https://ArtZoick.github.io/">
  <img class="avatar" src="https://ArtZoick.github.io//images/avatar.png?v=1572228390311" alt="">
  </a>
  <h1 class="site-title">
    清汤牛肉锅
  </h1>
  <p class="site-description">
    温故而知新

  </p>
  <div class="menu-container">
    
      
        <a href="/" class="menu">
          首页
        </a>
      
    
      
        <a href="/archives" class="menu">
          归档
        </a>
      
    
      
        <a href="/tags" class="menu">
          标签
        </a>
      
    
      
        <a href="/post/about" class="menu">
          关于
        </a>
      
    
      
        <a href="/post/beef" class="menu">
          牛肉锅
        </a>
      
    
  </div>
  <div class="social-container">
    
      
    
      
    
      
    
      
    
      
    
  </div>
</div>

        <div class="post-detail">
          <article class="post">
            <h2 class="post-title">
              SpringMVC_2 响应数据、文件上传、异常处理、拦截器
            </h2>
            <div class="post-info">
              <span>
                2019-07-26
              </span>
              <span>
                18 min read
              </span>
              
                <a href="https://ArtZoick.github.io//tag/springmvc" class="post-tag">
                  # SpringMVC
                </a>
              
                <a href="https://ArtZoick.github.io//tag/framework" class="post-tag">
                  # 框架
                </a>
              
            </div>
            
            <div class="post-content-wrapper">
              <div class="post-content">
                <h2 id="一-响应数据和结果视图">一、响应数据和结果视图</h2>
<h3 id="1-返回值分类">1、返回值分类</h3>
<h4 id="1返回字符串">(1)返回字符串</h4>
<p>Controller方法返回字符串可以指定逻辑视图的名称，根据<strong>视图解析器</strong>解析为物理视图的地址。</p>
<pre><code class="language-java">@RequestMapping(value = &quot;/hello&quot;)
    public String sayHello() {
        System.out.println(&quot;Hello SpringMVC!!&quot;);
        // 跳转到XX页面
        return &quot;success&quot;;
    }
</code></pre>
<p>具体的应用场景</p>
<pre><code class="language-java"> /**
     * 返回值是String
     *
     * @param model
     * @return
     */
    @RequestMapping(&quot;/testString&quot;)
    public String testString(Model model) {
        System.out.println(&quot;testString方法执行了&quot;);
        //模拟从数据库查询出了User对象
        User user = new User();
        user.setUsername(&quot;彭于晏&quot;);
        user.setPassword(&quot;123&quot;);
        user.setAge(20);

        //model对象 addAttribute第一个参数是key值，第二个参数是user对象
        model.addAttribute(&quot;user&quot;, user);

        return &quot;success&quot;;
    }
</code></pre>
<pre><code class="language-jsp">&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; isELIgnored=&quot;false&quot; %&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Title&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h3&gt;执行成功&lt;/h3&gt;
${user.username}
${user.password}
&lt;/body&gt;
&lt;/html&gt;

</code></pre>
<p><strong>注意点:</strong><br>
可将数据存储到model对象中，然后在success.jsp中用${user.username}将属性取出来</p>
<h4 id="2返回值是void">(2)返回值是void</h4>
<p>如果控制器的方法返回值编写成void，执行程序报404的异常，默认查找JSP页面没有找到。<br>
　　默认会跳转到 @RequestMapping(&quot;/testVoid&quot;)  testVoid的页面。</p>
<p>可以使用请求转发或者重定向跳转到指定的页面</p>
<pre><code class="language-java"> /**
     * 返回值是void，默认情况会去寻找方法请求路径名的testVoid.jsp
     *
     * @param request response
     * @return
     */
    @RequestMapping(&quot;/testVoid&quot;)
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println(&quot;testVoid方法执行了&quot;);
        //1、编写请求转发的程序,不会经过视图解析器，要将目录写完整
        //request.getRequestDispatcher(&quot;/WEB-INF/pages/success.jsp&quot;).forward(request,response);
        
        //2、重定向，重新发的新请求不能访问WEb—INF/pages里的页面的
        //response.sendRedirect(request.getContextPath()+&quot;/index.jsp&quot;);
        
        //3、直接会进行响应，响应json数据
        //设置解决中文乱码问题
        response.setCharacterEncoding(&quot;UTF-8&quot;);
        response.setContentType(&quot;text/html;charset=UTF-8&quot;);
        
        response.getWriter().print(&quot;hello 你好&quot;);
        return;//不想让后面的代码继续执行加一个return
    }
</code></pre>
<h4 id="3返回值是modelandview对象">(3)返回值是ModelAndView对象</h4>
<p>ModelAndView对象是Spring提供的一个对象，可以用来调整具体的JSP视图</p>
<p>具体的代码如下</p>
<pre><code class="language-java">   /**
     * 返回ModelAndView
     *
     * @return
     */
    @RequestMapping(&quot;/testModelAndView&quot;)
    public ModelAndView testModelAndView() {

        //创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        System.out.println(&quot;testModelAndView方法执行了&quot;);
        //模拟从数据库查询出了User对象
        User user = new User();
        user.setUsername(&quot;吴彦祖&quot;);
        user.setPassword(&quot;123123&quot;);
        user.setAge(20);

        //把user对象存储到mv对象中，也会把user对象存入到request对象
        mv.addObject(&quot;user&quot;, user);

        //跳转到哪个页面,这里会走视图解析器
        mv.setViewName(&quot;success&quot;);
        return mv;
    }
</code></pre>
<p><strong>注意:</strong> 在页面上上获取使用的是 requestScope.username 取的，所以返回 ModelAndView 类型时，浏<br>
览器跳转只能是请求转发。</p>
<h3 id="2-springmvc框架提供的请求转发和重定向">2、SpringMVC框架提供的请求转发和重定向</h3>
<p>controller方法返回String类型，请求转发的代码如下</p>
<pre><code class="language-java">/**
     * 使用关键字的方式进行转发或重定向
     *
     * @return
     */
    @RequestMapping(&quot;/testForwardOrRedirect&quot;)
    public String testForwardOrRedirect() {
        System.out.println(&quot;testForwardOrRedirect方法执行了&quot;);

        //1、请求的转发，不会走视图解析器，将路径写完整
        //return &quot;forward:/WEB-INF/pages/success.jsp&quot;;

        //2、重定向 不用加项目名，注意和转发不同
        return &quot;redirect:/index.jsp&quot;;
    }
</code></pre>
<p><strong>注意:</strong><br>
1、如果用了 forward：则路径必须写成实际视图 url，不能写逻辑视图。<br>
　它相当于“request.getRequestDispatcher(&quot;url&quot;).forward(request,response)”。使用请求转发，既可以转发到 jsp，也可以转发到其他的控制器方法。<br>
2、使用redirect：如果是重定向到 jsp 页面，则 jsp 页面不能写在 WEB-INF 目录中，否则无法找到</p>
<h3 id="3-responsebody响应json数据">3、ResponseBody响应json数据</h3>
<p><strong>前言:</strong> 该注解用于将 Controller 的方法返回的对象，通过 HttpMessageConverter 接口转换为指定格式的<br>
数据如：json,xml 等，通过 Response 响应给客户端</p>
<p>DispatcherServlet 会拦截到所有的资源，导致一个问题就是静态资源（img、css、js）也会被拦截到，从而不能被使用。解决问题就是需要配置静态资源不进行拦截，在 springmvc.xml 配置文件添加如下配置</p>
<h4 id="1mvcresources标签配置不过滤">(1)mvc:resources标签配置不过滤</h4>
<p>location元素表示webapp目录下的包下的所有文件<br>
　　mapping元素表示以/static开头的所有请求路径，如/static/a 或者/static/a/b</p>
<pre><code class="language-xml"> &lt;!--前端控制器，那些静态资源不拦截--&gt;
    &lt;mvc:resources location=&quot;/css/&quot; mapping=&quot;/css/**&quot;/&gt; &lt;!-- 样式 --&gt;
    &lt;mvc:resources location=&quot;/images/&quot; mapping=&quot;/images/**&quot;/&gt; &lt;!-- 图片 --&gt;
    &lt;mvc:resources location=&quot;/js/&quot; mapping=&quot;/js/**&quot;/&gt; &lt;!-- javascript --&gt;
</code></pre>
<h4 id="2-使用requestbody获取请求体数据">(2) 使用@RequestBody获取请求体数据</h4>
<p>json字符串和JavaBean对象互相转换的过程中，需要使用jackson的jar包</p>
<pre><code class="language-xml">&lt;!--json字符串和JavaBean对象互相转换的过程中，需要使用jackson的jar包--&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;com.fasterxml.jackson.core&lt;/groupId&gt;
            &lt;artifactId&gt;jackson-databind&lt;/artifactId&gt;
            &lt;version&gt;2.9.0&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;com.fasterxml.jackson.core&lt;/groupId&gt;
            &lt;artifactId&gt;jackson-core&lt;/artifactId&gt;
            &lt;version&gt;2.9.0&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;com.fasterxml.jackson.core&lt;/groupId&gt;
            &lt;artifactId&gt;jackson-annotations&lt;/artifactId&gt;
            &lt;version&gt;2.9.0&lt;/version&gt;
        &lt;/dependency&gt;
</code></pre>
<p>使用@RequestBody注解把json的字符串转换成JavaBean的对象</p>
<pre><code class="language-java">/**
     * 模拟异步响应请求
     * Ajax传的是json数据，获得请求体的内容，请求体的内容是传的json的字符串
     */
    @RequestMapping(&quot;/testAjax&quot;)
    public @ResponseBody User testAjax(@RequestBody User user) {
        System.out.println(&quot;testAjax方法执行了&quot;);
        //客户端发送ajax请求，传的是json字符串，后端把json字符串封装到user对象中
        System.out.println(user);

        //做响应，模拟查询数据库
        user.setUsername(&quot;zoick&quot;);

        //做响应,返回的是对象，但是前端还是json数据
        return user;
    }
</code></pre>
<pre><code class="language-jsp">&lt;script src=&quot;js/jquery.min.js&quot;&gt;&lt;/script&gt;

    &lt;script&gt;
        // 页面加载，绑定单击事件
        $(function(){
            $(&quot;#btn&quot;).click(function(){
                // alert(&quot;hello btn&quot;);
                // 发送ajax请求
                $.ajax({
                    // 编写json格式，设置属性和值
                    url:&quot;user/testAjax&quot;,//后台的请求方法
                    contentType:&quot;application/json;charset=UTF-8&quot;,
                    data:'{&quot;username&quot;:&quot;hehe&quot;,&quot;password&quot;:&quot;123&quot;,&quot;age&quot;:30}',//json数据，将会传到服务器
                    dataType:&quot;json&quot;,
                    type:&quot;post&quot;,
                    success:function(data){
                        // data服务器端响应的json的数据，进行解析
                        alert(data);
                        alert(data.username);
                        alert(data.password);
                        alert(data.age);
                    }
                });

            });
        });

    &lt;/script&gt;
</code></pre>
<h2 id="二-springmvc实现文件上传">二、SpringMVC实现文件上传</h2>
<h3 id="0-文件上传的必要前提">0、文件上传的必要前提</h3>
<pre><code class="language-xml">1、form 表单的 enctype 取值必须是：multipart/form-data
           (默认值是:application/x-www-form-urlencoded)
           enctype:是表单请求正文的类型
2、method 属性取值必须是 Post
3、提供一个文件选择域&lt;input type=”file” /&gt;
</code></pre>
<h3 id="1-传统文件上传方式">1、传统文件上传方式</h3>
<h4 id="1导入文件上传的jar包">(1)导入文件上传的jar包</h4>
<pre><code class="language-xml"> &lt;!--文件上传--&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;commons-fileupload&lt;/groupId&gt;
      &lt;artifactId&gt;commons-fileupload&lt;/artifactId&gt;
      &lt;version&gt;1.3.1&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;commons-io&lt;/groupId&gt;
      &lt;artifactId&gt;commons-io&lt;/artifactId&gt;
      &lt;version&gt;2.4&lt;/version&gt;
    &lt;/dependency&gt;

&lt;!--使用 Commons-fileupload 组件实现文件上传，需要导入该组件相应的支撑 jar 包：Commons-fileupload 和commons-io。commons-io 不属于文件上传组件的开发 jar 文件，但Commons-fileupload 组件从 1.1 版本开始，它工作时需要 commons-io 包的支持。--&gt;
</code></pre>
<h4 id="2文件上传的jsp页面">(2)文件上传的JSP页面</h4>
<pre><code class="language-jsp">&lt;h3&gt;传统方式文件上传&lt;/h3&gt;
&lt;form action=&quot;user/fileupload1&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
    选择文件:&lt;input type=&quot;file&quot; name=&quot;upload&quot;/&gt; &lt;br/&gt;
    &lt;input type=&quot;submit&quot; value=&quot;上传&quot;/&gt;

&lt;/form&gt;
</code></pre>
<h4 id="3文件上传的controller控制器">(3)文件上传的Controller控制器</h4>
<pre><code class="language-java">@RequestMapping(&quot;/fileupload1&quot;)
    public String fileupload1(HttpServletRequest request) throws Exception {
        System.out.println(&quot;文件上传...&quot;);

        //使用fileupload组件完成文件上传
        //上传的位置
        String path = request.getSession().getServletContext().getRealPath(&quot;/uploads/&quot;);
        //判断该路径是否存在
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }

        //解析request对象，获取上传文件项
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload upload = new ServletFileUpload(factory);
        //解析request
        List&lt;FileItem&gt; items = upload.parseRequest(request);
        //遍历
        for (FileItem item : items) {
            //进行判断，当前item对象是否上传文件项
            if (item.isFormField()) {
                //true说明普通表单项
            } else {
                //说明上传文件项
                //获取上传文件的名称
                String filename = item.getName();
                //把文件名设为唯一值，uuid
                String uuid = UUID.randomUUID().toString().replace(&quot;-&quot;, &quot;&quot;);
                filename = filename + uuid;
                //完成文件上传
                item.write(new File(path, filename));
                //删除临时文件
                item.delete();
            }
        }

        return &quot;success&quot;;
    }
</code></pre>
<h3 id="2-springmvc方式文件上传">2、SpringMVC方式文件上传</h3>
<p>SpringMVC框架提供了<strong>MultipartFile对象</strong>，该对象表示上传的文件，<em><strong>要求变量名称必须和表单file标签的name属性名称相同。</strong></em></p>
<h4 id="1在springmvc中配置文件解析器对象">(1)在spring.mvc中配置文件解析器对象</h4>
<pre><code class="language-xml">&lt;!--配置文件解析器对象 id值是固定的--&gt;
    &lt;bean id=&quot;multipartResolver&quot; class=&quot;org.springframework.web.multipart.commons.CommonsMultipartResolver&quot;&gt;
        &lt;property name=&quot;maxUploadSizePerFile&quot; value=&quot;10485760&quot;/&gt;
    &lt;/bean&gt;
</code></pre>
<p><strong>注意:</strong> 文件上传的解析器 id 是固定的，不能起别的名称，否则无法实现请求参数的绑定。（不光是文件，其他字段也将无法绑定</p>
<h4 id="2文件上传的jsp页面-2">(2)文件上传的JSP页面</h4>
<pre><code class="language-jsp">&lt;h3&gt;SpringMVC文件上传&lt;/h3&gt;
&lt;form action=&quot;user/fileupload2&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
    选择文件:&lt;input type=&quot;file&quot; name=&quot;upload&quot;/&gt; &lt;br/&gt;
    &lt;input type=&quot;submit&quot; value=&quot;上传&quot;/&gt;

&lt;/form&gt;
</code></pre>
<h4 id="3文件用springmvc框架上传的controller控制器">(3)文件用SpringMVC框架上传的Controller控制器</h4>
<pre><code class="language-java">@RequestMapping(&quot;/fileupload2&quot;)
    //注意MultipartFile中形参的名字要和jsp中的表单的名字相同
public String fileupload2(HttpServletRequest request, MultipartFile upload) throws Exception {
        System.out.println(&quot;SpringMVC文件上传...&quot;);

        //使用fileupload组件完成文件上传
        //上传的位置
        String path = request.getSession().getServletContext().getRealPath(&quot;/uploads/&quot;);
        //判断该路径是否存在
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }


        //说明上传文件项
        //获取上传文件的名称
        String filename = upload.getOriginalFilename();
            
        // 把文件的名称设置唯一值，uuid
        String uuid = UUID.randomUUID().toString().replace(&quot;-&quot;, &quot;&quot;);
        filename = uuid+&quot;_&quot;+filename;
        //完成文件上传
       upload.transferTo(new File(path,filename));

        return &quot;success&quot;;
    }
</code></pre>
<h3 id="3-springmvc跨服务器方式文件上传">3、SpringMVC跨服务器方式文件上传</h3>
<h4 id="1搭建tomcat图片服务器">(1)搭建tomcat图片服务器</h4>
<h4 id="2导入所需要的jar包">(2)导入所需要的jar包</h4>
<pre><code class="language-xml">&lt;!--跨服务器上传需要的jar包--&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;com.sun.jersey&lt;/groupId&gt;
      &lt;artifactId&gt;jersey-core&lt;/artifactId&gt;
      &lt;version&gt;1.18.1&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;com.sun.jersey&lt;/groupId&gt;
      &lt;artifactId&gt;jersey-client&lt;/artifactId&gt;
      &lt;version&gt;1.18.1&lt;/version&gt;
    &lt;/dependency&gt;
</code></pre>
<h4 id="3文件上传的jsp页面">(3)文件上传的JSP页面</h4>
<pre><code class="language-jsp">&lt;h3&gt;跨服务器文件上传&lt;/h3&gt;
&lt;form action=&quot;user/fileupload3&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
    选择文件:&lt;input type=&quot;file&quot; name=&quot;upload&quot;/&gt; &lt;br/&gt;
    &lt;input type=&quot;submit&quot; value=&quot;上传3&quot;/&gt;

&lt;/form&gt;
</code></pre>
<h4 id="4文件上传的controller控制器">(4)文件上传的Controller控制器</h4>
<pre><code class="language-java">/**
     * 跨服务器文件上传
     * @return
     */
    @RequestMapping(&quot;/fileupload3&quot;)
    public String fileuoload3(MultipartFile upload) throws Exception {
        System.out.println(&quot;跨服务器文件上传...&quot;);

        // 定义上传文件服务器路径
        String path = &quot;http://localhost:9090/uploads/&quot;;

        // 说明上传文件项
        // 获取上传文件的名称
        String filename = upload.getOriginalFilename();
        // 把文件的名称设置唯一值，uuid
        String uuid = UUID.randomUUID().toString().replace(&quot;-&quot;, &quot;&quot;);
        filename = uuid+&quot;_&quot;+filename;

        // 创建客户端的对象
        Client client = Client.create();

        // 和图片服务器进行连接
        WebResource webResource = client.resource(path + filename);

        // 上传文件
        webResource.put(upload.getBytes());

        return &quot;success&quot;;
    }

</code></pre>
<h2 id="三-springmvc的异常处理">三、SpringMVC的异常处理</h2>
<h3 id="1-异常处理思路">1、异常处理思路</h3>
<p>Controller调用service，service调用dao，异常都是向上抛出的，最终有DispatcherServlet找异常处理器进行异常的处理。</p>
<figure data-type="image" tabindex="1"><img src="https://ArtZoick.github.io//post-images/springmvc/exception_1.bmp" alt=""></figure>
<h3 id="2-springmvc的异常处理">2、SpringMVC的异常处理</h3>
<h4 id="1自定义异常类">(1)自定义异常类</h4>
<pre><code class="language-java">
@Getter
@Setter
public class SysException extends Exception{

    //存储提示信息的
    private String message;


    public SysException(String message) {
        this.message = message;
    }
}

</code></pre>
<h4 id="2自定义异常处理器">(2)自定义异常处理器</h4>
<pre><code class="language-java">public class SysExceptionResolver implements HandlerExceptionResolver {

    /**
     * 处理异常的业务逻辑
     *
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param ex
     * @return
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception ex) {

        //获取异常对象
        SysException e = null;
        if (ex instanceof SysException) {
            //如果抛出的是系统自定义异常则直接转换
            e = (SysException) ex;
        }else {
            //如果抛出的不是系统自定义异常则重新构造一个系统错误异常
            e = new SysException(&quot;系统正在维护...&quot;);
        }

        //创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        mv.addObject(&quot;errorMsg&quot;,e.getMessage());
        mv.setViewName(&quot;error&quot;);
        return mv;
    }
}
</code></pre>
<h4 id="3在springmvc中配置异常处理器">(3)在spring.mvc中配置异常处理器</h4>
<pre><code class="language-xml">&lt;!--配置异常处理器--&gt;
&lt;bean id=&quot;sysException&quot; class=&quot;top.zoick.exception.SysExceptionResolver&quot;/&gt;
</code></pre>
<h2 id="四-springmvc框架中的拦截器">四、SpringMVC框架中的拦截器</h2>
<h3 id="1-拦截器的概述">1、拦截器的概述</h3>
<p>1、SpringMVC框架中的拦截器用于对处理器进行预处理和后处理的技术。</p>
<p>2、可以定义拦截器链，连接器链就是将拦截器按着一定的顺序结成一条链，在访问被拦截的方法时，拦截器链<br>
中的拦截器会按着定义的顺序执行。</p>
<p>3、拦截器和过滤器的功能比较类似，有区别</p>
<p><strong>过滤器</strong>是Servlet规范的一部分，任何框架都可以使用过滤器技术。<br>
　　<strong>拦截器</strong>是SpringMVC框架独有的。<br>
　　<strong>过滤器</strong>配置了/*，可以拦截任何资源。<br>
　　<strong>拦截器</strong>只会对控制器中的方法进行拦截。</p>
<p>4、拦截器也是AOP思想的一种实现方式</p>
<p>5、想要自定义拦截器，需要实现HandlerInterceptor接口。</p>
<h3 id="2-自定义拦截器步骤">2、自定义拦截器步骤</h3>
<h4 id="1创建类实现handlerinterceptor接口重写需要的方法">(1)创建类，实现HandlerInterceptor接口，重写需要的方法</h4>
<pre><code class="language-java">public class MyInterceptor1 implements HandlerInterceptor {
    /**
     * 预处理，controller方法执行前，实际开发场景：登录页面是否登录的逻辑判断
     * return true 放行，执行下一个拦截器，如果没有，执行controller中的方法
     * return false 不放行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println(&quot;MyInterceptor1执行了......前111&quot;);
        //request.getRequestDispatcher(&quot;/WEB-INF/pages/error.jsp&quot;).forward(request,response);

        return true;
    }

    /**
     * 后处理方法，此方法执行与controller方法执行后，success.jsp执行前
     * 可用来释放资源，关闭流
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println(&quot;MyInterceptor1执行了......后111&quot;);
        //request.getRequestDispatcher(&quot;/WEB-INF/pages/error.jsp&quot;).forward(request,response);

    }

    /**
     * success.jsp方法执行后，该方法会执行
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println(&quot;MyInterceptor1执行了......最后111&quot;);
    }
}

</code></pre>
<h4 id="2在springmvcxml中配置多个拦截器类">(2)在springmvc.xml中配置多个拦截器类</h4>
<pre><code class="language-xml">&lt;!--配置拦截器--&gt;
    &lt;mvc:interceptors&gt;
        &lt;!--配置拦截器--&gt;
        &lt;mvc:interceptor&gt;
            &lt;!--要拦截的具体方法--&gt;
            &lt;mvc:mapping path=&quot;/user/*&quot;/&gt;
            &lt;!--配置拦截器对象--&gt;
            &lt;bean class=&quot;top.zoick.interceptor.MyInterceptor1&quot;/&gt;
        &lt;/mvc:interceptor&gt;

        &lt;!--配置第二个拦截器--&gt;
        &lt;mvc:interceptor&gt;
            &lt;!--要拦截的具体方法--&gt;
            &lt;mvc:mapping path=&quot;/**&quot;/&gt;
            &lt;!--配置拦截器对象--&gt;
            &lt;bean class=&quot;top.zoick.interceptor.MyInterceptor2&quot;/&gt;
        &lt;/mvc:interceptor&gt;

    &lt;/mvc:interceptors&gt;
</code></pre>
<h4 id="3多个拦截器执行流程">(3)多个拦截器执行流程</h4>
<figure data-type="image" tabindex="2"><img src="https://ArtZoick.github.io//post-images/springmvc/interceptor_1.bmp" alt=""></figure>
<h3 id="3-handlerinterceptor接口中的方法">3、HandlerInterceptor接口中的方法</h3>
<h4 id="1prehandle方法是controller方法执行前拦截的方法">(1)preHandle方法是controller方法执行前拦截的方法</h4>
<p>可以使用request或者response跳转到指定的页面<br>
return true放行，执行下一个拦截器，如果没有拦截器，执行controller中的方法。<br>
return false不放行，不会执行controller中的方法。</p>
<h4 id="2posthandle是controller方法执行后执行的方法在jsp视图执行前">(2)postHandle是controller方法执行后执行的方法，在JSP视图执行前。</h4>
<p>可以使用request或者response跳转到指定的页面<br>
如果指定了跳转的页面，那么controller方法跳转的页面将不会显示。</p>
<h4 id="3posthandle方法是在jsp执行后执行">(3)postHandle方法是在JSP执行后执行</h4>
<p>request或者response不能再跳转页面了</p>
<hr>
<p>源码:<a href="https://github.com/ArtZoick/MyBatis">点🐔这里</a></p>

              </div>
              <div class="toc-container">
                <ul class="markdownIt-TOC">
<li>
<ul>
<li><a href="#%E4%B8%80-%E5%93%8D%E5%BA%94%E6%95%B0%E6%8D%AE%E5%92%8C%E7%BB%93%E6%9E%9C%E8%A7%86%E5%9B%BE">一、响应数据和结果视图</a>
<ul>
<li><a href="#1-%E8%BF%94%E5%9B%9E%E5%80%BC%E5%88%86%E7%B1%BB">1、返回值分类</a>
<ul>
<li><a href="#1%E8%BF%94%E5%9B%9E%E5%AD%97%E7%AC%A6%E4%B8%B2">(1)返回字符串</a></li>
<li><a href="#2%E8%BF%94%E5%9B%9E%E5%80%BC%E6%98%AFvoid">(2)返回值是void</a></li>
<li><a href="#3%E8%BF%94%E5%9B%9E%E5%80%BC%E6%98%AFmodelandview%E5%AF%B9%E8%B1%A1">(3)返回值是ModelAndView对象</a></li>
</ul>
</li>
<li><a href="#2-springmvc%E6%A1%86%E6%9E%B6%E6%8F%90%E4%BE%9B%E7%9A%84%E8%AF%B7%E6%B1%82%E8%BD%AC%E5%8F%91%E5%92%8C%E9%87%8D%E5%AE%9A%E5%90%91">2、SpringMVC框架提供的请求转发和重定向</a></li>
<li><a href="#3-responsebody%E5%93%8D%E5%BA%94json%E6%95%B0%E6%8D%AE">3、ResponseBody响应json数据</a>
<ul>
<li><a href="#1mvcresources%E6%A0%87%E7%AD%BE%E9%85%8D%E7%BD%AE%E4%B8%8D%E8%BF%87%E6%BB%A4">(1)mvc:resources标签配置不过滤</a></li>
<li><a href="#2-%E4%BD%BF%E7%94%A8requestbody%E8%8E%B7%E5%8F%96%E8%AF%B7%E6%B1%82%E4%BD%93%E6%95%B0%E6%8D%AE">(2) 使用@RequestBody获取请求体数据</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E4%BA%8C-springmvc%E5%AE%9E%E7%8E%B0%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0">二、SpringMVC实现文件上传</a>
<ul>
<li><a href="#0-%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E7%9A%84%E5%BF%85%E8%A6%81%E5%89%8D%E6%8F%90">0、文件上传的必要前提</a></li>
<li><a href="#1-%E4%BC%A0%E7%BB%9F%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E6%96%B9%E5%BC%8F">1、传统文件上传方式</a>
<ul>
<li><a href="#1%E5%AF%BC%E5%85%A5%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E7%9A%84jar%E5%8C%85">(1)导入文件上传的jar包</a></li>
<li><a href="#2%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E7%9A%84jsp%E9%A1%B5%E9%9D%A2">(2)文件上传的JSP页面</a></li>
<li><a href="#3%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E7%9A%84controller%E6%8E%A7%E5%88%B6%E5%99%A8">(3)文件上传的Controller控制器</a></li>
</ul>
</li>
<li><a href="#2-springmvc%E6%96%B9%E5%BC%8F%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0">2、SpringMVC方式文件上传</a>
<ul>
<li><a href="#1%E5%9C%A8springmvc%E4%B8%AD%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%A7%A3%E6%9E%90%E5%99%A8%E5%AF%B9%E8%B1%A1">(1)在spring.mvc中配置文件解析器对象</a></li>
<li><a href="#2%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E7%9A%84jsp%E9%A1%B5%E9%9D%A2-2">(2)文件上传的JSP页面</a></li>
<li><a href="#3%E6%96%87%E4%BB%B6%E7%94%A8springmvc%E6%A1%86%E6%9E%B6%E4%B8%8A%E4%BC%A0%E7%9A%84controller%E6%8E%A7%E5%88%B6%E5%99%A8">(3)文件用SpringMVC框架上传的Controller控制器</a></li>
</ul>
</li>
<li><a href="#3-springmvc%E8%B7%A8%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%96%B9%E5%BC%8F%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0">3、SpringMVC跨服务器方式文件上传</a>
<ul>
<li><a href="#1%E6%90%AD%E5%BB%BAtomcat%E5%9B%BE%E7%89%87%E6%9C%8D%E5%8A%A1%E5%99%A8">(1)搭建tomcat图片服务器</a></li>
<li><a href="#2%E5%AF%BC%E5%85%A5%E6%89%80%E9%9C%80%E8%A6%81%E7%9A%84jar%E5%8C%85">(2)导入所需要的jar包</a></li>
<li><a href="#3%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E7%9A%84jsp%E9%A1%B5%E9%9D%A2">(3)文件上传的JSP页面</a></li>
<li><a href="#4%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E7%9A%84controller%E6%8E%A7%E5%88%B6%E5%99%A8">(4)文件上传的Controller控制器</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E4%B8%89-springmvc%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86">三、SpringMVC的异常处理</a>
<ul>
<li><a href="#1-%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E6%80%9D%E8%B7%AF">1、异常处理思路</a></li>
<li><a href="#2-springmvc%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86">2、SpringMVC的异常处理</a>
<ul>
<li><a href="#1%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BC%82%E5%B8%B8%E7%B1%BB">(1)自定义异常类</a></li>
<li><a href="#2%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E5%99%A8">(2)自定义异常处理器</a></li>
<li><a href="#3%E5%9C%A8springmvc%E4%B8%AD%E9%85%8D%E7%BD%AE%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E5%99%A8">(3)在spring.mvc中配置异常处理器</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E5%9B%9B-springmvc%E6%A1%86%E6%9E%B6%E4%B8%AD%E7%9A%84%E6%8B%A6%E6%88%AA%E5%99%A8">四、SpringMVC框架中的拦截器</a>
<ul>
<li><a href="#1-%E6%8B%A6%E6%88%AA%E5%99%A8%E7%9A%84%E6%A6%82%E8%BF%B0">1、拦截器的概述</a></li>
<li><a href="#2-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8B%A6%E6%88%AA%E5%99%A8%E6%AD%A5%E9%AA%A4">2、自定义拦截器步骤</a>
<ul>
<li><a href="#1%E5%88%9B%E5%BB%BA%E7%B1%BB%E5%AE%9E%E7%8E%B0handlerinterceptor%E6%8E%A5%E5%8F%A3%E9%87%8D%E5%86%99%E9%9C%80%E8%A6%81%E7%9A%84%E6%96%B9%E6%B3%95">(1)创建类，实现HandlerInterceptor接口，重写需要的方法</a></li>
<li><a href="#2%E5%9C%A8springmvcxml%E4%B8%AD%E9%85%8D%E7%BD%AE%E5%A4%9A%E4%B8%AA%E6%8B%A6%E6%88%AA%E5%99%A8%E7%B1%BB">(2)在springmvc.xml中配置多个拦截器类</a></li>
<li><a href="#3%E5%A4%9A%E4%B8%AA%E6%8B%A6%E6%88%AA%E5%99%A8%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B">(3)多个拦截器执行流程</a></li>
</ul>
</li>
<li><a href="#3-handlerinterceptor%E6%8E%A5%E5%8F%A3%E4%B8%AD%E7%9A%84%E6%96%B9%E6%B3%95">3、HandlerInterceptor接口中的方法</a>
<ul>
<li><a href="#1prehandle%E6%96%B9%E6%B3%95%E6%98%AFcontroller%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%E5%89%8D%E6%8B%A6%E6%88%AA%E7%9A%84%E6%96%B9%E6%B3%95">(1)preHandle方法是controller方法执行前拦截的方法</a></li>
<li><a href="#2posthandle%E6%98%AFcontroller%E6%96%B9%E6%B3%95%E6%89%A7%E8%A1%8C%E5%90%8E%E6%89%A7%E8%A1%8C%E7%9A%84%E6%96%B9%E6%B3%95%E5%9C%A8jsp%E8%A7%86%E5%9B%BE%E6%89%A7%E8%A1%8C%E5%89%8D">(2)postHandle是controller方法执行后执行的方法，在JSP视图执行前。</a></li>
<li><a href="#3posthandle%E6%96%B9%E6%B3%95%E6%98%AF%E5%9C%A8jsp%E6%89%A7%E8%A1%8C%E5%90%8E%E6%89%A7%E8%A1%8C">(3)postHandle方法是在JSP执行后执行</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

              </div>
            </div>
          </article>
        </div>

        
          <div class="next-post">
            <div class="next">下一篇</div>
            <a href="https://ArtZoick.github.io//post/springmvc_1">
              <h3 class="post-title">
                SpringMVC_1 入门、参数绑定、常用注解
              </h3>
            </a>
          </div>
        

        
          
            <link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">
<script src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>

<div id="gitalk-container"></div>

<script>

  var gitalk = new Gitalk({
    clientID: 'a2471d09bddb5be481ee',
    clientSecret: '05d427fb27f873cfabace27b9f042f2c7f23000f',
    repo: 'ArtZoick.github.io',
    owner: 'ArtZoick',
    admin: ['ArtZoick'],
    id: (location.pathname).substring(0, 49),      // Ensure uniqueness and length less than 50
    distractionFreeMode: false  // Facebook-like distraction free mode
  })

  gitalk.render('gitalk-container')

</script>

          

          
        

        <div class="site-footer">
  <a href="https://zhidao.baidu.com/question/1867120235416383707.html" target="_blank" onclick="alert('盲生，你发现了华点！');">学习强国</a>

<!--Tido对话插件-->
<script src="//code.tidio.co/5fh6jaqvluqj8jjuf5zlqrf5tlzpktnx.js"></script>
<style>
.text-popup {
    animation: textPopup 1s;
    color: red;
    user-select: none;
    white-space: nowrap;
    position: absolute;
    z-index: 99;
}
@keyframes textPopup {
    0%, 100% {
        opacity: 0;
    }
    5% {
        opacity: 1;
    }
    100% {
        transform: translateY(-50px);    
    }
}
</style>
<script type="text/javascript" src="https://cdn.bootcss.com/canvas-nest.js/1.0.1/canvas-nest.min.js">
!function(){function n(n,e,t){return n.getAttribute(e)||t}function e(n){return document.getElementsByTagName(n)}
function t(){var t=e("script"),o=t.length,i=t[o-1];return{l:o,z:n(i,"zIndex",-1),o:n(i,"opacity",.5),c:n(i,"color","0,0,0")
,n:n(i,"count",99)}}function o(){a=m.width=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidt
h,c=m.height=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight}function i(){r.clearRect
(0,0,a,c);var n,e,t,o,m,l;s.forEach(function(i,x){for(i.x+=i.xa,i.y+=i.ya,i.xa*=i.x>a||i.x<0?-1:1,i.ya*=i.y>c||i.y<0?-1:1,r.
fillRect(i.x-.5,i.y-.5,1,1),e=x+1;e<u.length;e++)n=u[e],null!==n.x&&null!==n.y&&(o=i.x-n.x,m=i.y-n.y,l=o*o+m*m,l<n.max&&(n===
y&&l>=n.max/2&&(i.x-=.03*o,i.y-=.03*m),t=(n.max-l)/n.max,r.beginPath(),r.lineWidth=t/2,r.strokeStyle="rgba("+d.c+","+(t+.2)+")
",r.moveTo(i.x,i.y),r.lineTo(n.x,n.y),r.stroke()))}),x(i)}var a,c,u,m=document.createElement("canvas"),d=t(),l="c_n"+d.l,r=m.
getContext("2d"),x=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.
oRequestAnimationFrame||window.msRequestAnimationFrame||function(n){window.setTimeout(n,1e3/45)},w=Math.random,y={x:null,y:nul
l,max:2e4};m.id=l,m.style.cssText="position:fixed;top:0;left:0;z-index:"+d.z+";opacity:"+d.o,e("body")[0].appendChild(m),o(),
window.οnresize=o,window.οnmοusemοve=function(n){n=n||window.event,y.x=n.clientX,y.y=n.clientY},window.οnmοuseοut=function(){y
.x=null,y.y=null};for(var s=[],f=0;d.n>f;f++){var h=w()*a,g=w()*c,v=2*w()-1,p=2*w()-1;s.push({x:h,y:g,xa:v,ya:p,max:6e3})}u=
s.concat([y]),setTimeout(function(){i()},100)}();
</script>

<!--鼠标点击-->
<!--富强-->
<script type="text/javascript"> 
/* 鼠标特效 */ 
var a_idx = 0; 
jQuery(document).ready(function($) { 
    $("body").click(function(e) { 
        var a = new Array("富强", "民主", "文明", "和谐", "自由", "平等", "公正" ,"法治", "爱国", "敬业", "诚信", "友善"); 
        var $i = $("<span/>").text(a[a_idx]); 
        a_idx = (a_idx + 1) % a.length; 
        var x = e.pageX, 
        y = e.pageY; 
        $i.css({ 
            "z-index": 999, 
            "top": y - 20, 
            "left": x, 
            "position": "absolute", 
            "font-weight": "bold", 
            "color": "#ff6651" 
        }); 
        $("body").append($i); 
        $i.animate({ 
            "top": y - 180, 
            "opacity": 0 
        }, 
        1500, 
        function() { 
            $i.remove(); 
        }); 
    }); 
}); 
</script>
<!--edn--富强--> | 
  <a class="rss" href="https://ArtZoick.github.io//atom.xml" target="_blank">RSS</a>
</div>

<script>
  hljs.initHighlightingOnLoad()

  let mainNavLinks = document.querySelectorAll(".markdownIt-TOC a");

  // This should probably be throttled.
  // Especially because it triggers during smooth scrolling.
  // https://lodash.com/docs/4.17.10#throttle
  // You could do like...
  // window.addEventListener("scroll", () => {
  //    _.throttle(doThatStuff, 100);
  // });
  // Only not doing it here to keep this Pen dependency-free.

  window.addEventListener("scroll", event => {
    let fromTop = window.scrollY;

    mainNavLinks.forEach((link, index) => {
      let section = document.getElementById(decodeURI(link.hash).substring(1));
      let nextSection = null
      if (mainNavLinks[index + 1]) {
        nextSection = document.getElementById(decodeURI(mainNavLinks[index + 1].hash).substring(1));
      }
      console.log('section.offsetHeight', section.offsetHeight);
      if (section.offsetTop <= fromTop) {
        if (nextSection) {
          if (nextSection.offsetTop > fromTop) {
            link.classList.add("current");
          } else {
            link.classList.remove("current");    
          }
        } else {
          link.classList.add("current");
        }
      } else {
        link.classList.remove("current");
      }
    });
  });

</script>

      </div>
    </div>
  </body>
</html>
